﻿using AutoMapper;
using ManagementApi.Authorizers;
using ManagementApi.Models;
using ManagementApi.Models.Manage.ProjectSpecialAccount;
using ManagementApi.Mvc;
using ManagementApi.Mvc.ApplicationContexts;
using ManagementApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Modules.BankSpecialAccount;
using Modules.BankSpecialAccount.Entitys;
using Modules.Common;
using Modules.Project;
using NPOI.SS.UserModel;
using PmSoft.Utilities;
using static Modules.BankSpecialAccount.BankSpecialAccountConstants;

namespace ManagementApi.Controllers.CommanderPannel
{
    /// <summary>
    /// 项目管理员-专户申请接口
    /// </summary>
    [Route("/api/v1/commander/projectspecialaccount")]
    [ApiController]
    [Authorize(Roles = "Commander")]
    public class ProjectSpecialAccountController : ControllerBase
    {
        private readonly BankSpecialAccountService projectSpecialAccountService;
        private readonly BankSpecialAccountPaymentService projectSpecialAccountPaymentService;
        private readonly BankSpecialAccountChangeStatusLogService projectSpecialAccountChangeStatusLogService;
        private readonly ProjectCommanderApplicationContext applicationContext;
        private readonly SerialNumberService serialNumberService;
        private readonly ProjectService projectService;
        private readonly IMapper mapper;
        private readonly ProjectOwnAuthorizer ownAuthorizer;

        public ProjectSpecialAccountController(BankSpecialAccountService projectSpecialAccountService, BankSpecialAccountChangeStatusLogService projectSpecialAccountChangeStatusLogService, ProjectCommanderApplicationContext applicationContext, IMapper mapper, SerialNumberService serialNumberService, ProjectService projectService, BankSpecialAccountPaymentService projectSpecialAccountPaymentService, ProjectOwnAuthorizer ownAuthorizer)
        {
            this.projectSpecialAccountService = projectSpecialAccountService;
            this.projectSpecialAccountChangeStatusLogService = projectSpecialAccountChangeStatusLogService;
            this.applicationContext = applicationContext;
            this.mapper = mapper;
            this.serialNumberService = serialNumberService;
            this.projectService = projectService;
            this.projectSpecialAccountPaymentService = projectSpecialAccountPaymentService;
            this.ownAuthorizer = ownAuthorizer;
        }

        /// <summary>
        /// author:hzj date:2023/12/21 describe:申请专户
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        [HttpPost("create")]
        public ApiResult CreateProjectSpecialAccount(ProjectSpecialAccountEditForm form)
        {
            if (projectSpecialAccountService.GetProjectSpecialAccountCount(applicationContext.CurrentProjectInfo.ProjectId) > 0)
                return ApiResult.Failure("当前项目已经申请过专户,不能重复申请");
            if (string.IsNullOrEmpty(form.Code))
            {
            }
            ProjectInfo? projectInfo = projectService.GetProjectInfo(applicationContext.CurrentProjectInfo.ProjectId);
            if (projectInfo == null) return ApiResult.Failure("项目信息不存在");
            BankSpecialAccountInfo entity = new();
            mapper.Map(form, entity);
            entity.ProjectId = applicationContext.CurrentProjectInfo.ProjectId;
            entity.CreateTime = DateTime.Now;
            entity.AccountStatus = 专户状态.开户中;
            entity.Creator = applicationContext.CurrentUser?.Name;
            projectSpecialAccountService.CreateProjectSpecialAccount(entity);
            return ApiResult.Success("创建成功", entity);
        }

        /// <summary>
        /// author:hzj date:2023/12/21 describe:获取指定专户数据
        /// </summary>
        /// <param name="id">专户id，若ID=0，则只获取单据号</param>
        /// <returns></returns>
        [HttpGet("{id}/form")]
        public ApiResult<ProjectSpecialAccountDto> GetProjectSpecialAccount(int id)
        {
            ProjectInfo? projectInfo = projectService.GetProjectInfo(applicationContext.CurrentProjectInfo.ProjectId);
            ProjectSpecialAccountDto dto = new();
            if (projectInfo == null) return ApiResult<ProjectSpecialAccountDto>.Failure("项目信息不存在");
            if (id == 0)
            {
                dto.Code = serialNumberService.GetSerialNumber(SerialNumberType.专户, projectInfo.PrjNum, projectInfo.ProjectId);
                return ApiResult<ProjectSpecialAccountDto>.Success(dto);
            }
            BankSpecialAccountInfo? data = projectSpecialAccountService.GetProjectSpecialAccount(id);
            if (data == null)
                return ApiResult<ProjectSpecialAccountDto>.Failure("专户不存在");
            return ApiResult<ProjectSpecialAccountDto>.Success(data.AsProjectSpecialAccountDto(applicationContext));
        }

        /// <summary>
        /// author:hzj date:2023/12/21 describe:获取专户列表
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <param name="pageNum">页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns></returns>
        [HttpGet("page")]
        public ApiResult<PageDto<ProjectSpecialAccountDto>> GetProjectSpecialAccounts([FromQuery] BankSpecialAccountQuery query, int pageNum = 1, int pageSize = 20)
        {
            query.ProjectId = applicationContext.CurrentProjectInfo.ProjectId;
            var data = projectSpecialAccountService.GetProjectSpecialAccounts(query, pageNum, pageSize);
            var dtos = data.AsPageDto(source => { return source.AsProjectSpecialAccountDto(applicationContext); });
            return ApiResult<PageDto<ProjectSpecialAccountDto>>.Success(dtos);
        }

        /// <summary>
        /// author:hzj date:2023/12/21 describe:获取收支明细
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <param name="pageNum">页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns></returns>
        [HttpGet("page_payment")]
        public ApiResult<PageDto<ProjectSpecialAccountPaymentDto>> GetProjectSpecialAccountPayments([FromQuery] BankSpecialAccountPaymentQuery query, int pageNum = 1, int pageSize = 20)
        {
            query.ProjectId = applicationContext.CurrentProjectInfo.ProjectId;
            var data = projectSpecialAccountPaymentService.GetProjectSpecialAccountPayments(query, pageNum, pageSize);
            var dtos = data.AsPageDto(source => { return source.AsProjectSpecialAccountPaymentDto(applicationContext); });
            return ApiResult<PageDto<ProjectSpecialAccountPaymentDto>>.Success(dtos);
        }

        /// <summary>
        /// 导出收支明细
        /// </summary>
        /// <param name="query"></param>
        /// <param name="pageNum"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        [HttpGet("export_payment")]
        public IActionResult ExportPayment([FromQuery] BankSpecialAccountPaymentQuery query, int pageNum = 1, int pageSize = 999999)
        {
            query.ProjectId = applicationContext.CurrentProjectInfo.ProjectId;
            var data = projectSpecialAccountPaymentService.GetProjectSpecialAccountPayments(query, pageNum, pageSize);
            IWorkbook workbook = ExcelExportHelper.ExportToExcel(data.AsExportDto());
            // 将工作簿保存到内存流中
            using (MemoryStream memoryStream = new MemoryStream())
            {
                workbook.Write(memoryStream);
                // 返回文件内容结果
                return File(memoryStream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"专户收支信息_{DateTime.Now.ToString("yyyyMMddHHmmss ")}.xlsx");
            }
        }

        /// <summary>
        /// author:hzj date:2023/12/21 describe:删除专户
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpDelete("{ids}")]
        public ApiResult Delete(string ids)
        {
            var data = projectSpecialAccountPaymentService.GetProjectSpecialAccountPayments(ValueUtility.ConvertToList<int>(ids));

            #region 数据权限验证

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(data.Select(i => i.ProjectId));

            #endregion 数据权限验证

            projectSpecialAccountService.DeletProjectSpecialAccounts(ValueUtility.ConvertToList<int>(ids));
            return ApiResult.Success("删除成功");
        }
    }
}